local skynet = require "skynet"
require "skynet.manager"
local socket = require "socket"
local buffrw = require "buffrw"
local CMD    = require "center_proto"

local center_fd = 0
local center_ip = ""
local center_port = 0
local room_type = 0
local game_id   = 0
local table_pre = 0
local last_recv_time = 0
local Manager = nil

local center_reconnect = false

local REQ = {}
local lreq = {}
local lfunctin = {}

function lreq.send_package(fd, pack)
	local package = string.pack(">s2", pack)
	socket.write(fd, package)
end

function lreq.recv_pack(msg, sz)
    if sz >= 4 then
        local mcmd,scmd = string.unpack(">I2>I2", msg, 1) 
        lreq.OnRecvMsg(mcmd, scmd, string.unpack("c"..sz-4, msg, 5) , sz-4)
    end
end

function lreq.connect_game(ip, port)
    center_reconnect = true
    center_fd = socket.open(ip, port)
    if not center_fd  then 
        skynet.error("connect to center  fail  ip="..ip.." port="..port )
        return false
    end
    center_reconnect = false
    center_ip = ip; center_port = port

    lreq.RegServer()

    skynet.error("connect to center ip="..ip.." port="..port.." fd="..center_fd)
    if center_fd > 0 then
        skynet.fork(function()
            while true do
                local len = 0
                local read_size = socket.read(center_fd, 2)
                if not read_size  then
                
                    skynet.error("1 connect fd closed, try connect to:"..center_ip.." "..center_port )
                    socket.close(center_fd)
                    center_reconnect = true;
                    break
                else
                    len = string.unpack(">I2", read_size)
                end
                
                if len > 0 then
                    local r = socket.read(center_fd, len)
                    if not r then
                        skynet.error("find center_fd closed")
                        break
                    else
                        lreq.recv_pack(r, len)
                    end
                end  
            end
        end)
        return true
    end
    return false
end

function lreq.timerToCenter()
    local data = buffrw.BuffWrite.new()
    data:proto(CMD.Main_Center_module, CMD.Sub_ModuleToCenter_CheckNet)
    lreq.send_package(center_fd, data.buff)
end

function lreq.RegServer()
    local data = buffrw.BuffWrite.new()
    data:proto(CMD.Main_Center_module, CMD.Sub_ModuleToCenter_GSReg)
    data:int4(game_id)
    data:int2(table_pre)
    data:int2(room_type)
    lreq.send_package(center_fd, data.buff)
end

function lreq.CheckNetTime()
    
    local cu_time = os.time()
    if last_recv_time ~= 0 and cu_time > last_recv_time and (cu_time - last_recv_time) > 30 then
        skynet.error("connect center fail, time out")
    end
end

function lreq.OnRecvHallMsg(mcmd, scmd, msg,sz)
    skynet.send(".manager","lua","OnRecvHallMsg", mcmd, scmd, msg, sz)
end

function lreq.OnRecvMsg(mcmd, scmd, msg, sz)
    
    last_recv_time = os.time()

    if mcmd ~= CMD.Main_Center_module then 
        skynet.error("lreq.OnRecvMsg ", mcmd, scmd)
    end

    if mcmd == CMD.Main_Center_module then
        if scmd == CMD.Sub_ModuleToCenter_CheckNet then
            lreq.CheckNetTime()
        end

    elseif mcmd == CMD.Main_hall_module 
        or mcmd == CMD.Main_match_module then

        lreq.OnRecvHallMsg(mcmd, scmd, msg, sz)
    end
end

function lreq.startTimerFunction()
    skynet.fork(function()
        while true do
            skynet.sleep(500)   
            --发送重连接信号
            if not center_reconnect then
                lreq.timerToCenter()
            else  
                lreq.connect_game(center_ip, center_port) 
            end
        end
    end)
end

function REQ.sendToCenter(mscmd, scmd, msg)
    local data = buffrw.BuffWrite.new()
    data:proto(mscmd, scmd)
    data:str(msg, #msg)
    lreq.send_package(center_fd, data.buff)
end

function REQ.start(conf)
    center_ip   = conf.center_ip
    center_port = conf.center_port
    room_type   = conf.room_type
    table_pre   = conf.table_pre
    game_id     = conf.game_id

    lreq.connect_game(center_ip, center_port) 

    lreq.startTimerFunction()
end

function REQ.exit()
    skynet.exit()
end

skynet.start(function()
    print("center_con start")
	skynet.dispatch("lua", function(_,_, command, ...)
		local f = REQ[command]
		skynet.ret(skynet.pack(f(...)))
	end)
   -- skynet.register ".center_con"
    Manager = skynet.localname(".manager")


    skynet.register(".center_con")
end)
